﻿
package com.jwt.vpower.view.components.videoplayer.model
{
	import flash.events.*;
	import flash.events.EventDispatcher;
	import org.openvideoplayer.net.*;
	import org.openvideoplayer.events.*;
	import com.akamai.net.*
		import flash.net.NetStream;
	import com.jwt.vpower.view.components.videoplayer.events.VideoPlayerEvent;
	import com.jwt.vpower.model.Debugger;
	
	public class VideoPlayerModel extends EventDispatcher
	{
		private var _connection:*;
		public var _stream:*;
		private var _host : String
		private var _duration:Number;
		private var _videoFile :String
		private var _currentHost :String;
		private var _debugger : Debugger
		private var _handleVideoModelFunction : Function;
		private var _isStreaming : Boolean;
		
		
		public function VideoPlayerModel(){_debugger=Debugger.instance}
		
		
		public function handleModel($function:Function):void{
			_handleVideoModelFunction=$function
			addEventListener(VideoPlayerEvent.STREAM_COMPLETE,_handleVideoModelFunction);
			addEventListener(VideoPlayerEvent.STREAM_LENGTH,_handleVideoModelFunction);
			addEventListener(VideoPlayerEvent.PLAYING_VIDEO,_handleVideoModelFunction);
		}
		
		public function connectToServer($host:String,$file:String)
		{_videoFile=$file
			if(_connection==null){
				
				_debugger.debug("VideoPLayerModel","NEW CONNECTION")
				/* if there is a host then it streams other wise it is in its local directory*/
				if($host!=""){
					connectToStreamingServer($host,$file)
				}else{
					progressiveVideo($file)
				}
				
			}else{
				
				if($host==_currentHost){
					if($host!=""){
						_connection.connect($host);
					}else{
						destroy();
						handleModel(_handleVideoModelFunction);
						connectToServer($host,$file);
					}
				}else{
					destroy();
					trace(" reconnect ");
					handleModel(_handleVideoModelFunction);
					connectToServer($host,$file);
				}
				
			}
			
			
		}
		
		
		private function progressiveVideo($file:String):void{
			_isStreaming=false;
			trace(" progresssive");
			_connection = new OvpConnection()
			_connection.addEventListener(OvpEvent.ERROR, errorHandler);
			_connection.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
			_connection.connect(null);
			
		}
		private function connectToStreamingServer($host:String,$file:String):void{
			_isStreaming=true;
			trace(" streaming");
			_connection = new AkamaiConnection();
			_connection.addEventListener(OvpEvent.BANDWIDTH,onBandWidthHandler);
			_connection.addEventListener(OvpEvent.STREAM_LENGTH,onStreamLengthHandler);
			_connection.addEventListener(NetStatusEvent.NET_STATUS,netStatusHandler);
			_connection.addEventListener(OvpEvent.ERROR,onError);
			_connection.requestedProtocol = "rtmpe,rtmp";
			_connection.requestedPort="any";
			_connection.connect($host);
			_currentHost=$host;
		}
		
		
		// Handles a successful bandwidth measurement
		private function onBandWidthHandler(e:OvpEvent):void {
			_debugger.debug(this,("The bandwidth is " + e.data.bandwidth + "kbps and the latency is " + e.data.latency + " ms."))
			// At this point, you could use the bandwidth value to decide which file to play.
			_connection.requestStreamLength(_videoFile);
		}
		
		
		
		
		
		// This method is called from the netStatusHandler below when we receive a good connection		
		private function connectedHandler():void {
			_debugger.debug(this,("Successfully connected to: "));
			_debugger.debug(this,("is Streaming: " + _isStreaming))
			
			if(_isStreaming){
				_connection.detectBandwidth();
				_stream = new AkamaiNetStream(_connection.netConnection);
				
				_stream.addEventListener(OvpEvent.COMPLETE,onCompleteHandler);
				_stream.addEventListener(NetStatusEvent.NET_STATUS, streamStatusHandler);
				_stream.addEventListener(OvpEvent.ASYNC_ERROR, asyncErrorHandler);
				_stream.addEventListener(OvpEvent.STREAM_LENGTH,onStreamLengthHandler); 
			}else{
				//trace(" normal connection");
				_stream = new OvpNetStream(_connection);
				
				// Add the necessary listeners
				_stream.addEventListener(OvpEvent.COMPLETE,onCompleteHandler);
				_stream.addEventListener(NetStatusEvent.NET_STATUS, streamStatusHandler);
				_stream.addEventListener(OvpEvent.ASYNC_ERROR, asyncErrorHandler);
				//_stream.addEventListener(OvpEvent.NETSTREAM_PLAYSTATUS, streamPlayStatusHandler);
				_stream.addEventListener(OvpEvent.NETSTREAM_METADATA, metadataHandler);
				//_stream.addEventListener(OvpEvent.STREAM_LENGTH,onStreamLengthHandler); 
				
				
				dispatchEvent(new VideoPlayerEvent(VideoPlayerEvent.STREAM_LENGTH,_stream));
				_stream.play(_videoFile);
				
			}
		}	
		
		private function onHandleProgress(e:OvpEvent):void{
			
			dispatchEvent(new VideoPlayerEvent(VideoPlayerEvent.STREAM_PROGRESS,null));
			
		}
		
		private function onCompleteHandler(e:OvpEvent):void
		{
			//closeStream();
			trace(" video complete");
			dispatchEvent(new VideoPlayerEvent(VideoPlayerEvent.STREAM_COMPLETE,null))
		}
		public function duration():Number
		{
			return _duration;
		}
		
		
		public function stream():NetStream
		{
			return _stream;
		}
		private function onStreamLengthHandler(e:OvpEvent):void {
			trace(" stream length");
			
			_duration = e.data.streamLength;
			dispatchEvent(new VideoPlayerEvent(VideoPlayerEvent.STREAM_LENGTH,_stream));
			_stream.play(_videoFile);
			
			
		}
		
		public function streamTime():Number
		{
			return _stream.time
		}
		
		public function get streamSoundVolume():Number
		{
			return _stream.volume
		}
		
		public function set streamSoundVolume($volume:Number):void
		{
			_stream.volume=$volume
		}
		public function seekStream($frame:Number):void
		{
			_stream.seek($frame);
		}
		public function pauseStream():void
		{
			_stream.pause();
		}
		public function closeStream():void
		{
			_debugger.debug(this,"CLOSE STREAM")
			if(_stream){
				_stream.close();
				
			}
		}
		
		public function resumeStream():void
		{
			_stream.resume();
		}
		
		public function destroy():void
		{
			if(_stream){
				closeStream()
				_stream.removeEventListener(OvpEvent.COMPLETE,onCompleteHandler);
				_stream.removeEventListener(NetStatusEvent.NET_STATUS, streamStatusHandler);
				_stream.removeEventListener(OvpEvent.STREAM_LENGTH, streamLengthHandler); 
				_stream.removeEventListener(OvpEvent.NETSTREAM_METADATA, metadataHandler);
				_stream=null;
				
				_connection.removeEventListener(OvpEvent.BANDWIDTH,onBandWidthHandler);
				_connection.removeEventListener(OvpEvent.STREAM_LENGTH,onStreamLengthHandler);
				_connection.removeEventListener(NetStatusEvent.NET_STATUS,netStatusHandler);
				_connection.removeEventListener(OvpEvent.ERROR,onError);
				_connection=null
			}	
			
			removeEventListener(VideoPlayerEvent.STREAM_COMPLETE,_handleVideoModelFunction);
			removeEventListener(VideoPlayerEvent.STREAM_LENGTH,_handleVideoModelFunction);
			removeEventListener(VideoPlayerEvent.PLAYING_VIDEO,_handleVideoModelFunction);
		}
		
		
		// Handles the OvpEvent.NETSTREAM_METADATA events fired by the OvpNetStream class	
		private function metadataHandler(e:OvpEvent):void {
			
			
			_duration = e.data.duration;
			
			trace(" duration " + _duration);
		}
		
		// Handles all OvpEvent.ERROR events
		private function errorHandler(e:OvpEvent):void {
			_debugger.debug(this,("Error #" + e.data.errorNumber+": " + e.data.errorDescription, "ERROR"))
				
		}
		
		
		// Handles the stream length event fired by the OvpNetStream class when "duration" is found in the metadata for the FLV file
		private function streamLengthHandler(e:OvpEvent):void {
			_debugger.debug(this,("Stream length is " + e.data.streamLength))
			
		}
		
		// Handles NetStatusEvent.NET_STATUS events fired by the OvpConnection class
		private function netStatusHandler(e:NetStatusEvent):void {
			
			switch (e.info.code) {
				case "NetConnection.Connect.Rejected":
					_debugger.debug(this,("Rejected by server. Reason is "+e.info.description))
					
					
					break;
				case "NetConnection.Connect.Success":
					_debugger.debug(this,"CONNECTION SUCCESSFUL")
					connectedHandler();
					break;
			}
		}
		
		
		// Handles any errors dispatched by the connection class.
		private function onError(e:OvpEvent):void {
			_debugger.debug(this,("Error: " + e.data.errorDescription))
			
		}
		
		// Handles the NetStatusEvent.NET_STATUS events fired by the OvpNetStream class			
		private function streamStatusHandler(e:NetStatusEvent):void {
			//_debugger.debug(this, ("streamStatusHandler() - event.info.code="+e.info.code))
			
			
			
			switch(e.info.code)
			{
				case("NetStream.Play.Start"):
					//if(!_isDragging){
					//_isRunning=true;
					//}
					dispatchEvent(new VideoPlayerEvent(VideoPlayerEvent.PLAYING_VIDEO,"play"));
					break;
				
				case("NetStream.Pause.Notify"):
					//_isRunning=false;
					dispatchEvent(new VideoPlayerEvent(VideoPlayerEvent.PLAYING_VIDEO,"pause"));
					break;
				
				
			}
		}
		
		private function asyncErrorHandler($event:AsyncErrorEvent):void{
			//trace(" AsyncErrorEvent " + $event);
		}
		
		public function onCalculate_Framefraction( p1: Number, p2 : Number)
		{
			var frame_fraction = ( p1 - p2 ) /_duration ;
			return frame_fraction;
		}
		
		public function onGotoFrame( p1 : Number , p2 : Number, xpos : Number, indicatorW : Number)
		{
			var frame_fraction =onCalculate_Framefraction( p1 , p2 );
			var newX = xpos + indicatorW;
			var frame : Number = Math.round(newX / frame_fraction);
			_stream.seek(frame);
		}
	}
}

